package 网络编程.tcpEchoServerClient;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

/*
实现回显服务器-客户端
利用 TCP 协议
 */
public class TcpEchoServer {
    private ServerSocket server = null;  // 作用就是拉客, 建立连接后, 将连接拿到应用程序中

    public TcpEchoServer(int port) throws IOException {
        server = new ServerSocket(port); // 绑定端口号
    }

    // 长连接, 多个请求, 多个响应
    public void start() throws IOException {
        System.out.println("服务器启动");
        ExecutorService threadPool = Executors.newCachedThreadPool();
        while (true) {
            Socket socket = server.accept(); // 拉客!! 建立连接, 通过 Socket 对象进行数据传输, 没有连接就阻塞
            // 版本 1 : 无法被多个客户端访问
            // processConnect(socket);  // 长连接, 多请求, 多响应

            // 版本 2 : 如果线程数量太多, 效率很较低
            /*new Thread(() -> {
                try {
                    processConnect(socket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }).start();*/

            // 版本 3 : 线程池
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnect(socket);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }

    private void processConnect(Socket socket) throws IOException {
        System.out.printf("[%s | %d] 建立连接\n", socket.getInetAddress().toString(), socket.getPort());

        try (InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream()) {
            Scanner scanner = new Scanner(inputStream);
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {// 1. 读取请求
                if (!scanner.hasNext()) {
                    System.out.println("断开连接");
                    break;
                }
                String request = scanner.next();
                // 2. 加工响应
                String response = process(request);
                // 3. 发送响应
                printWriter.println(response); // 写入响应后, 加个换行, 当 scanner.next() 的结束符
                printWriter.flush();
                System.out.printf("[%s  |  %d] request: %s  |  response: %s\n",
                        socket.getInetAddress(), socket.getPort(), request, response);
                }
        } finally {
            socket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(6666);
        server.start();
    }
}